; File encoding:  UTF-8
;http://blog.csdn.net/liuyukuan/article/details/8349832
;~ 按win+-显示任务栏上按钮标号
;~ 标号是用字母标识
;~ 按win+字母 切换

;~ 原版：
;Quick task switching with Win+[1,2,...,0]
;Win + 数字键 切换，用 Win - 可能看到任务栏标号，然后再 Win + 数字 切换
;http://www.autohotkey.com/forum/viewtopic.php?t=41542&highlight=taskbar+order+switch
#SingleInstance
#WinActivateForce
Build_hWndArray(26)
Loop  %g_bundleCount%
  {
    sym:=Chr(A_Index+96)
    Hotkey, #%sym%, %sym%
  }
Return
a:
  RemoveToolTips()
  n:=Asc(A_ThisLabel)-96
  FocusButton(n)
Return
b:
  RemoveToolTips()
  n:=Asc(A_ThisLabel)-96
  FocusButton(n)
Return
c:
  RemoveToolTips()
  n:=Asc(A_ThisLabel)-96
  FocusButton(n)
Return
d:
  RemoveToolTips()
  n:=Asc(A_ThisLabel)-96
  FocusButton(n)
Return
e:
  RemoveToolTips()
  n:=Asc(A_ThisLabel)-96
  FocusButton(n)
Return
f:
  RemoveToolTips()
  n:=Asc(A_ThisLabel)-96
  FocusButton(n)
Return
g:
  RemoveToolTips()
  n:=Asc(A_ThisLabel)-96
  FocusButton(n)
Return
h:
  RemoveToolTips()
  n:=Asc(A_ThisLabel)-96
  FocusButton(n)
Return
i:
  RemoveToolTips()
  n:=Asc(A_ThisLabel)-96
  FocusButton(n)
Return
j:
  RemoveToolTips()
  n:=Asc(A_ThisLabel)-96
  FocusButton(n)
Return
k:
  RemoveToolTips()
  n:=Asc(A_ThisLabel)-96
  FocusButton(n)
Return
l:
  RemoveToolTips()
  n:=Asc(A_ThisLabel)-96
  FocusButton(n)
Return
m:
  RemoveToolTips()
  n:=Asc(A_ThisLabel)-96
  FocusButton(n)
Return
n:
  RemoveToolTips()
  n:=Asc(A_ThisLabel)-96
  FocusButton(n)
Return
o:
  RemoveToolTips()
  n:=Asc(A_ThisLabel)-96
  FocusButton(n)
Return
p:
  RemoveToolTips()
  n:=Asc(A_ThisLabel)-96
  FocusButton(n)
Return
q:
  RemoveToolTips()
  n:=Asc(A_ThisLabel)-96
  FocusButton(n)
Return
r:
  RemoveToolTips()
  n:=Asc(A_ThisLabel)-96
  FocusButton(n)
Return
s:
  RemoveToolTips()
  n:=Asc(A_ThisLabel)-96
  FocusButton(n)
Return
t:
  RemoveToolTips()
  n:=Asc(A_ThisLabel)-96
  FocusButton(n)
Return
u:
  RemoveToolTips()
  n:=Asc(A_ThisLabel)-96
  FocusButton(n)
Return
v:
  RemoveToolTips()
  n:=Asc(A_ThisLabel)-96
  FocusButton(n)
Return
w:
  RemoveToolTips()
  n:=Asc(A_ThisLabel)-96
  FocusButton(n)
Return
x:
  RemoveToolTips()
  n:=Asc(A_ThisLabel)-96
  FocusButton(n)
Return
y:
  RemoveToolTips()
  n:=Asc(A_ThisLabel)-96
  FocusButton(n)
Return
z:
  RemoveToolTips()
  n:=Asc(A_ThisLabel)-96
  FocusButton(n)
Return
;WIN+- shows button numbers as tooltips.

#-::
  WinShow ahk_class Shell_TrayWnd
  ShowToolTips()
Return

RemoveToolTips()
{
  Loop, 12
      ToolTip,,,,%A_Index%
}

ShowToolTips()
  {
    global g_bundleCount

    CoordMode, ToolTip, Screen
    Loop, %g_bundleCount%
      {
        ;~ If A_Index < 5
        ;~ continue

        x := g_xs%A_Index%
        y := g_ys%A_Index%
        ;~ If A_Index = 10
        ;~ text = 0
        ;~ Else
        ;~ text = %A_Index%
        text:=Chr(A_Index+96)
        ToolTip, %text%, %x%, %y%, %A_Index%
      }
  }

Add_hWndToArray(gi, hWnd)
  {
    global
    g_bundleSize%gi% := g_bundleSize%gi% + 1
    local wi := g_bundleSize%gi%
    g_hWnd%gi%_%wi% := hWnd
  }

AddBundle(gi)
  {
    global
    g_bundleSize%gi% := 0
  }

BundleSize(gi)
  {
    global
    Return g_bundleSize%gi%
  }

Get_hWndFromArray(gi, wi)
  {
    global
    Return g_hWnd%gi%_%wi%
  }

SetButtonTopLeftLoc(gi, x, y)
  {
    global
    g_xs%gi% := x
    g_ys%gi% := y
  }

Build_hWndArray(maxBundleCount)
  {
    global g_bundleCount

    WinGet,	pidTaskbar, PID, ahk_class Shell_TrayWnd
    hProc := DllCall("OpenProcess", "Uint", 0x38, "int", 0, "Uint", pidTaskbar)
    pProc := DllCall("VirtualAllocEx", "Uint", hProc, "Uint", 0, "Uint", 32, "Uint", 0x1000, "Uint", 0x4)
    idxTB := GetTaskSwBar()
    SendMessage, 0x418, 0, 0, ToolbarWindow32%idxTB%, ahk_class Shell_TrayWnd ; TB_ButtonCount
    ButtonCount := ErrorLevel

    g_bundleCount := 0

    Loop, %ButtonCount%
      {
        SendMessage, 0x417, A_Index-1, pProc, ToolbarWindow32%idxTB%, ahk_class Shell_TrayWnd ; TB_GETButton

        VarSetCapacity(btn, 32, 0)
        DllCall("ReadProcessMemory", "Uint", hProc, "Uint", pProc, "Uint", &btn, "Uint", 32, "Uint", 0)

        idn	:= NumGet(btn, 4)
        Statyle := NumGet(btn, 8, "Char")
        dwData := NumGet(btn, 12)
        If Not dwData
            dwData := NumGet(btn, 16, "int64")

        DllCall("ReadProcessMemory", "Uint", hProc, "Uint", dwData, "int64P", hWnd:=0, "Uint", NumGet(btn,12) ? 4:8, "Uint", 0)

        If Not hWnd ; Group Button, indicates the start of a Group
          {
            If g_bundleCount >= %maxBundleCount%
                Break
            Hidden := Statyle & 0x08 ; TBSTATE_Hidden
            If Not Hidden
              {
                grpCollapsed := true
                g_bundleCount := g_bundleCount + 1
                AddBundle(g_bundleCount)

                GetTaskbarButtonTopLeft(idn, x, y)
                SetButtonTopLeftLoc(g_bundleCount, x, y)
              }
            Else
                grpCollapsed := false
          }
        Else ; actual window Button
          {
            If grpCollapsed
              {
                Add_hWndToArray(g_bundleCount, hWnd)
              }
            Else
              {
                g_bundleCount := g_bundleCount + 1
                AddBundle(g_bundleCount)
                Add_hWndToArray(g_bundleCount, hWnd)
                GetTaskbarButtonTopLeft(idn, x, y)
                SetButtonTopLeftLoc(g_bundleCount, x, y)
              }
          }
      }

    DllCall("VirtualFreeEx", "Uint", hProc, "Uint", pProc, "Uint", 0, "Uint", 0x8000)
    DllCall("CloseHandle", "Uint", hProc)
  }

FocusButton(n)
  {
    global g_bundleCount

    ; these static variables can become inaccurate if windows are created or closed
    ; inbetween pressing of hotkeys, but in practice, we can safely ignore the
    ; inaccuracy
    static prevBundleIndex := 0
    static prevWindowIndex := 0

    Build_hWndArray(n)

    If (g_bundleCount >= n)
      {
        bundleSize := BundleSize(n)

        If n = %prevBundleIndex%
            windowIndex := Mod(prevWindowIndex, bundleSize) + 1
        Else
            windowIndex := 1

        hWnd := Get_hWndFromArray(n, windowIndex)

        If bundleSize > 1 ; cycle through windows in the same bundle
            WinActivate, ahk_id %hWnd%
        Else ; Single-window bundle; Toggles Between activating (restoring) and minimizing the window
            IfWinActive, ahk_id %hWnd%
                WinMinimize, ahk_id %hWnd%
            Else
                WinActivate, ahk_id %hWnd%
        prevBundleIndex := n
        prevWindowIndex := windowIndex
      }
  }

GetTaskSwBar()
  {
    ControlGet, hParent, hWnd,, MSTaskSwWClass1 , ahk_class Shell_TrayWnd
    ControlGet, hChild , hWnd,, ToolbarWindow321, ahk_id %hParent%
    Loop
      {
        ControlGet, hWnd, hWnd,, ToolbarWindow32%A_Index%, ahk_class Shell_TrayWnd
        If Not hWnd
            Break
        Else If hWnd = %hChild%
          {
            idxTB := A_Index
            Break
          }
      }
    Return	idxTB
  }

GetTaskbarButtonTopLeft(id, ByRef x, ByRef y)
  {
    idxTB := GetTaskSwBar()
    WinGet,	pidTaskbar, PID, ahk_class Shell_TrayWnd
    hProc := DllCall("OpenProcess", "Uint", 0x38, "int", 0, "Uint", pidTaskbar)
    pProc := DllCall("VirtualAllocEx", "Uint", hProc, "Uint", 0, "Uint", 32, "Uint", 0x1000, "Uint", 0x4)
    idxTB := GetTaskSwBar()

    SendMessage, 0x433, id, pProc, ToolbarWindow32%idxTB%, ahk_class Shell_TrayWnd ; TB_GETRECT
    ;IfEqual, ErrorLevel, 0, return "Err: can't get rect"

    VarSetCapacity(rect, 32, 0)
    DllCall("ReadProcessMemory", "Uint", hProc, "Uint", pProc, "Uint", &rect, "Uint", 32, "Uint", 0)

    DllCall("VirtualFreeEx", "Uint", hProc, "Uint", pProc, "Uint", 0, "Uint", 0x8000)
    DllCall("CloseHandle", "Uint", hProc)

    ControlGet, hWnd, hWnd,, ToolbarWindow32%idxTB%, ahk_class Shell_TrayWnd
    WinGetPos, x, y, w, h, ahk_id %hWnd%

    left := NumGet(rect, 0)
    top := NumGet(rect, 4)
    Right := NumGet(rect, 8)
    Bottom := NumGet(rect, 12)

    x := x + left
    y := y + top
  }
